<template>
  <div class="role-container">
    <el-card>
      <el-button
        type="default"
        size="small"
        :style="btnStyle"
        style="margin-bottom: 15px"
        icon="el-icon-plus"
        @click="addOrEditRoleHandler(1)"
      >
        添加角色
      </el-button>
      <!-- 表格 -->
      <el-table
        :data="roleList"
        style="width: 100%"
        border
        stripe
        :style="fontStyle"
      >
        <el-table-column align="center" type="expand">
          <template slot-scope="{ row }">
            <!-- 一级权限 -->
            <el-row
              v-for="first in row.children"
              :key="first.id"
              class="first-label"
            >
              <el-col :span="4">
                <el-tag closable @close="delRoleAuthHandler(row, first)">
                  {{ first.authName }}</el-tag
                >
                <span class="el-icon-caret-right"></span>
              </el-col>
              <el-col :span="20">
                <!-- 二级权限 -->
                <el-row
                  v-for="(second, index) in first.children"
                  :key="second.id"
                  class="second-label"
                  :style="{
                    'border-bottom':
                      index === first.children.length - 1 && 'none',
                  }"
                >
                  <el-col :span="6">
                    <el-tag
                      type="success"
                      closable
                      @close="delRoleAuthHandler(row, second)"
                    >
                      {{ second.authName }}
                    </el-tag>
                    <span class="el-icon-caret-right"></span>
                  </el-col>
                  <el-col :span="18" class="three-label">
                    <!-- 三级权限 -->
                    <el-tag
                      type="info"
                      closable
                      v-for="three in second.children"
                      :key="three.id"
                      @close="delRoleAuthHandler(row, three)"
                    >
                      {{ three.authName }}
                    </el-tag>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column align="center" type="index" label="#">
        </el-table-column>
        <el-table-column
          align="center"
          prop="roleName"
          label="角色名称"
          width="width"
        >
        </el-table-column>
        <el-table-column
          align="center"
          prop="roleDesc"
          label="角色描述"
          width="width"
        >
        </el-table-column>
        <el-table-column align="center" label="操作" width="width">
          <template slot-scope="{ row }">
            <el-button
              size="small"
              :style="btnStyle"
              type="default"
              icon="el-icon-edit"
              @click="addOrEditRoleHandler(0, row)"
            >
              编辑
            </el-button>
            <el-button
              size="small"
              :style="btnStyle"
              type="default"
              icon="el-icon-delete"
              @click="delRoleHandler(row)"
            >
              删除
            </el-button>
            <el-button
              size="small"
              :style="btnStyle"
              type="default"
              icon="el-icon-star-off"
              @click="editRoleAuthHandler(row)"
            >
              分配权限
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 添加或编辑角色对话框 -->
      <el-dialog
        :title="title"
        :visible.sync="addOrEditDialogVisible"
        width="40%"
        :before-close="closeDialogHandler"
      >
        <el-form
          ref="addOrEditFormRef"
          :model="addOrEditForm"
          label-width="80px"
          :rules="addOrEditRules"
        >
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="addOrEditForm.roleName"></el-input>
          </el-form-item>
          <el-form-item label="角色描述">
            <el-input v-model="addOrEditForm.roleDesc"></el-input>
          </el-form-item>
        </el-form>
        <div slot="footer">
          <el-button @click="closeDialogHandler">取 消</el-button>
          <el-button @click="addOrEditRoleConfirm" :style="btnStyle">
            确 定
          </el-button>
        </div>
      </el-dialog>
      <!-- 分配权限树形列表 -->
      <el-dialog
        title=""
        :visible.sync="editRoleAuthDialogVisible"
        width="50%"
        :before-close="editRoleAuthBeforeClose"
      >
        <el-tree
          v-if="isShowTree"
          ref="treeRef"
          :data="authTree"
          :props="defaultProps"
          show-checkbox
          node-key="id"
          :default-checked-keys="defaultCheckedKeys"
          :default-expanded-keys="defaultCheckedKeys"
        >
        </el-tree>
        <div slot="footer">
          <el-button @click="editRoleAuthBeforeClose"> 取 消 </el-button>
          <el-button :style="btnStyle" @click="authTreeConfirmHandler">
            确 定
          </el-button>
        </div>
      </el-dialog>
    </el-card>
  </div>
</template>

<script>
import { mapActions, mapState } from 'vuex'
export default {
  name: 'role',
  data() {
    return {
      addOrEditDialogVisible: false, // 添加或编辑角色对话框状态
      title: '', // 添加或编辑角色对话框标题
      // 添加或编辑角色表单对象
      addOrEditForm: {
        roleName: '',
        roleDesc: '',
      },
      // 添加或编辑角色表单验证对象
      addOrEditRules: {
        roleName: [
          { required: true, message: '请填写角色名称', trigger: 'blur' },
        ],
      },
      editRoleAuthDialogVisible: false, // 分配权限对话框状态
      // 指定树形控件与数据之间的对应关系
      defaultProps: {
        children: 'children',
        label: 'authName',
      },
      defaultCheckedKeys: [], // 默认勾选的节点（存储节点的id）
      // 控制树形列表的状态，v-if让树形组件走挂载销毁流程，
      // 否则默认选中的节点数据无法渲染！！！（很重要）
      isShowTree: false,
      selectEditAuthRole: null, // 选中的编辑权限的角色
    }
  },
  computed: {
    ...mapState('role', ['roleList', 'authTree']),
  },
  methods: {
    ...mapActions('role', [
      'getRoleList',
      'addOrEditRole',
      'delRole',
      'delRoleAuth',
      'getAuthTree',
      'editRoleAuth',
    ]),
    // 关闭添加或编辑角色对话框回调
    closeDialogHandler(done) {
      // 清空残留数据及验证
      this.addOrEditForm = {}
      this.$refs.addOrEditFormRef.resetFields()
      // 判断是关闭还是隐藏
      typeof done == 'function' ? done() : (this.addOrEditDialogVisible = false)
    },
    /**
     * 添加或编辑角色
     * type 0编辑，1新增
     */
    addOrEditRoleHandler(type, role) {
      this.addOrEditDialogVisible = true
      if (type === 0) {
        this.title = '编辑角色'
        // 表单数据和展示的数据，不要存在引用关系
        this.addOrEditForm = JSON.parse(JSON.stringify(role))
      } else {
        this.title = '新增角色'
      }
    },
    // 点击添加或编辑角色确定按钮回调
    addOrEditRoleConfirm() {
      this.$refs.addOrEditFormRef.validate(async v => {
        if (!v) return
        const roleInfo = {
          id: this.addOrEditForm.id,
          params: this.addOrEditForm,
        }
        try {
          await this.addOrEditRole(roleInfo)
          this.closeDialogHandler()
          this.$message.success(this.title + '成功')
          this.getRoleList()
        } catch (error) {
          this.$message.error(error)
        }
      })
    },
    // 删除角色的回调
    async delRoleHandler(role) {
      try {
        await this.$messageBox.confirm('确定删除该角色吗？', '确认提示', {
          confirmButtonText: '确定删除',
          cancelButtonText: '我再想想',
        })
        try {
          await this.delRole(role.id)
          this.getRoleList()
          this.$message.success('删除角色成功')
        } catch (error) {
          this.$message.error(error)
        }
      } catch (error) {
        this.$message.info('已取消删除')
      }
    },
    // 点击删除角色指定权限回调
    async delRoleAuthHandler(role, auth) {
      try {
        await this.$messageBox.confirm(
          '此操作将永久删除该权限，是否继续？',
          '提示',
          {
            confirmButtonText: '确定删除',
            cancelButtonText: '我再想想',
          }
        )
        try {
          const params = {
            roleId: role.id,
            rightsId: auth.id,
          }
          const data = await this.delRoleAuth(params)
          this.$message.success('删除权限成功')
          // 会重新合上折叠区
          // this.getRoleList()

          // 将删除后返回的数据重新赋值即可
          role.children = data
        } catch (error) {
          this.$message.error(error)
        }
      } catch (error) {}
    },
    // 编辑用户权限
    editRoleAuthHandler(role) {
      // 获取用户已有的权限
      this.getDefaultKeys(role)
      this.editRoleAuthDialogVisible = true
      this.isShowTree = true
      this.selectEditAuthRole = role
    },
    // 递归获取三级权限id
    getDefaultKeys(node) {
      // 三级节点
      if (!node.children) return this.defaultCheckedKeys.push(node.id)

      node.children.forEach(item => this.getDefaultKeys(item))
    },
    // 关闭分配权限对话框
    editRoleAuthBeforeClose(done) {
      typeof done === 'function'
        ? done()
        : (this.editRoleAuthDialogVisible = false)
      // 清空选中的数组
      this.defaultCheckedKeys = []
      // 让树形组件销毁！！！
      this.isShowTree = false

      this.selectEditAuthRole = null
    },
    // 点击分配权限确定按钮回调
    async authTreeConfirmHandler() {
      // 获取选中节点或班选中节点的key
      const nodeArr = [
        ...this.$refs.treeRef.getHalfCheckedKeys(),
        ...this.$refs.treeRef.getCheckedKeys(),
      ]
      const params = {
        roleId: this.selectEditAuthRole.id,
        rids: nodeArr.join(','),
      }
      try {
        await this.editRoleAuth(params)
        this.$message.success('分配权限成功')
        this.editRoleAuthBeforeClose()
        this.getRoleList()
      } catch (error) {
        console.log(error)
      }
    },
  },
  mounted() {
    this.getRoleList()
    this.getAuthTree()
  },
}
</script>

<style lang="scss">
.role-container {
  .first-label {
    .el-tag {
      margin-left: 30px;
    }
  }
  .first-label,
  .second-label {
    display: flex;
    align-items: center;
    border-bottom: 1px solid #eee;
    .el-icon-caret-right {
      margin-left: 5px;
    }
    .three-label {
      .el-tag {
        margin: 8px;
      }
    }
  }
}
</style>
